﻿Imports System.Diagnostics
Imports System.Windows.Forms
Imports System.IO
Imports System.Xml.Schema
Imports System.Xml

Public Class NvExplorer
    Private mSchema As XmlSchema
    Private mDocData As XmlDataDocument
    Private Sub Explorer1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        'Set up the UI
        SetUpListViewColumns()
        LoadTree()
    End Sub

    Private Sub LoadTree()
        ' TODO: load nvpages and nvcategarys into tree

        Dim tvRoot As TreeNode
        Dim tvNode As TreeNode

        tvRoot = Me.TreeView.Nodes.Add("Root")
        tvNode = tvRoot.Nodes.Add("TreeItem1")
        tvNode = tvRoot.Nodes.Add("TreeItem2")
        tvNode = tvRoot.Nodes.Add("TreeItem3")
    End Sub

    Private Sub LoadListView()
        ' TODO: Add code to add items to the listview based on the selected item in the treeview

        Dim lvItem As ListViewItem
        ListView.Items.Clear()

        lvItem = ListView.Items.Add("ListViewItem1")
        lvItem.ImageKey = "Graph1"
        lvItem.SubItems.AddRange(New String() {"Column2", "Column3"})

        lvItem = ListView.Items.Add("ListViewItem2")
        lvItem.ImageKey = "Graph2"
        lvItem.SubItems.AddRange(New String() {"Column2", "Column3"})

        lvItem = ListView.Items.Add("ListViewItem3")
        lvItem.ImageKey = "Graph3"
        lvItem.SubItems.AddRange(New String() {"Column2", "Column3"})
    End Sub

    Private Sub SetUpListViewColumns()

        ' TODO: Add code to set up listview columns
        Dim lvColumnHeader As ColumnHeader

        ' Setting Column widths applies only to the current view, so this line
        '  explicitly sets the ListView to be showing the SmallIcon view
        '  before setting the column width
        SetView(View.SmallIcon)

        lvColumnHeader = ListView.Columns.Add("Column1")
        ' Set the SmallIcon view column width large enough so that the items
        '  do not overlap
        ' Note that the second and third column do not appear in SmallIcon
        '  view, so there is no need to set those while in SmallIcon view
        lvColumnHeader.Width = 90

        ' Change the view to Details and set up the appropriate column
        '  widths for the Details view differently than SmallIcon view
        SetView(View.Details)

        ' The first column needs to be slightly larger in Details view than it
        '  was for SmallIcon view, and Column2 and Column3 need explicit sizes
        '  set for Details view
        lvColumnHeader.Width = 100

        lvColumnHeader = ListView.Columns.Add("Column2")
        lvColumnHeader.Width = 70

        lvColumnHeader = ListView.Columns.Add("Column3")
        lvColumnHeader.Width = 70

    End Sub

    Private Sub ExitToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ExitToolStripMenuItem.Click
        'Close this form
        Me.Close()
    End Sub

    Private Sub ToolBarToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolBarToolStripMenuItem.Click
        'Toggle the visibility of the toolstrip and also the checked state of the associated menu item
        ToolBarToolStripMenuItem.Checked = Not ToolBarToolStripMenuItem.Checked
        ToolStrip.Visible = ToolBarToolStripMenuItem.Checked
    End Sub

    Private Sub StatusBarToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StatusBarToolStripMenuItem.Click
        'Toggle the visibility of the statusstrip and also the checked state of the associated menu item
        StatusBarToolStripMenuItem.Checked = Not StatusBarToolStripMenuItem.Checked
        StatusStrip.Visible = StatusBarToolStripMenuItem.Checked
    End Sub

    'Change whether or not the folders pane is visible
    Private Sub ToggleFoldersVisible()
        'First toggle the checked state of the associated menu item
        FoldersToolStripMenuItem.Checked = Not FoldersToolStripMenuItem.Checked

        'Change the Folders toolbar button to be in sync
        FoldersToolStripButton.Checked = FoldersToolStripMenuItem.Checked

        ' Collapse the Panel containing the TreeView.
        Me.SplitContainer.Panel1Collapsed = Not FoldersToolStripMenuItem.Checked
    End Sub

    Private Sub FoldersToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles FoldersToolStripMenuItem.Click
        ToggleFoldersVisible()
    End Sub

    Private Sub FoldersToolStripButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles FoldersToolStripButton.Click
        ToggleFoldersVisible()
    End Sub

    Private Sub SetView(ByVal View As System.Windows.Forms.View)
        'Figure out which menu item should be checked
        Dim MenuItemToCheck As ToolStripMenuItem = Nothing
        Select Case View
            Case View.Details
                MenuItemToCheck = DetailsToolStripMenuItem
            Case View.LargeIcon
                MenuItemToCheck = LargeIconsToolStripMenuItem
            Case View.List
                MenuItemToCheck = ListToolStripMenuItem
            Case View.SmallIcon
                MenuItemToCheck = SmallIconsToolStripMenuItem
            Case View.Tile
                MenuItemToCheck = TileToolStripMenuItem
            Case Else
                Debug.Fail("Unexpected View")
                View = View.Details
                MenuItemToCheck = DetailsToolStripMenuItem
        End Select

        'Check the appropriate menu item and deselect all others under the Views menu
        For Each MenuItem As ToolStripMenuItem In ListViewToolStripButton.DropDownItems
            If MenuItem Is MenuItemToCheck Then
                MenuItem.Checked = True
            Else
                MenuItem.Checked = False
            End If
        Next

        'Finally, set the view requested
        ListView.View = View
    End Sub

    Private Sub ListToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ListToolStripMenuItem.Click
        SetView(View.List)
    End Sub

    Private Sub DetailsToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DetailsToolStripMenuItem.Click
        SetView(View.Details)
    End Sub

    Private Sub LargeIconsToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles LargeIconsToolStripMenuItem.Click
        SetView(View.LargeIcon)
    End Sub

    Private Sub SmallIconsToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SmallIconsToolStripMenuItem.Click
        SetView(View.SmallIcon)
    End Sub

    Private Sub TileToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TileToolStripMenuItem.Click
        SetView(View.Tile)
    End Sub

    Private Sub OpenToolStripMenuItem_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles OpenToolStripMenuItem.Click
        Dim OpenFileDialog As New OpenFileDialog
        OpenFileDialog.InitialDirectory = My.Computer.FileSystem.SpecialDirectories.MyDocuments
        OpenFileDialog.Filter = "Text Files (*.txt)|*.txt"
        If OpenFileDialog.ShowDialog(Me) = Windows.Forms.DialogResult.OK Then

            Dim FileName As String = OpenFileDialog.FileName
            ' TODO: Add code to open the file
            Dim tr As New StreamReader(FileName)
            ' read the file into the XmlSchema object
            mSchema = XmlSchema.Read(tr, New ValidationEventHandler(AddressOf SchemaValidationHandler))
            tr.Close()
            ' report any problems with the mSchema by compiling it
            CompileSchema()
            ' create the document
            mDocData = New XmlDataDocument()
            ' open the mSchema again
            tr = New StreamReader(FileName)
            ' read it into the DataSet member
            mDocData.DataSet.ReadXmlSchema(tr)
            tr.Close()

            ConstructGUI(mDocData.DataSet)

        End If
    End Sub
  


    '=======================================================
    'Service provided by Telerik (www.telerik.com)
    'Conversion powered by NRefactory.
    'Built and maintained by Todd Anglin and Telerik
    '=======================================================

    Private Sub SaveAsToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) Handles SaveAsToolStripMenuItem.Click
        Dim SaveFileDialog As New SaveFileDialog
        SaveFileDialog.InitialDirectory = My.Computer.FileSystem.SpecialDirectories.MyDocuments
        SaveFileDialog.Filter = "Text Files (*.txt)|*.txt"
        SaveFileDialog.ShowDialog(Me)

        Dim FileName As String = SaveFileDialog.FileName
        ' TODO: Add code here to save the current contents of the form to a file.
    End Sub

    Private Sub TreeView_AfterSelect(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeViewEventArgs) Handles TreeView.AfterSelect
        ' TODO: Add code to change the listview contents based on the currently-selected node of the treeview
        LoadListView()
    End Sub
#Region "CompileSchema"
    ' Compile the schema as it exists in the XmlSchema structure, displaying any
    ' errors in the schema error edit box and displaying the schema itself in
    ' the schema edit box.
    Private Sub CompileSchema()
        mSchema.Compile(New ValidationEventHandler(AddressOf SchemaValidationHandler))
    End Sub

    Private Sub SchemaValidationHandler(ByVal sender As Object, ByVal args As ValidationEventArgs)
        MessageBox.Show(args.Message, "Schema compilation error:")
    End Sub
#End Region
#Region "Construct Gui"

    Private Sub ConstructGUI(ByVal dataSet As DataSet)
        ' clear the GUI
        ' not implemented

        Dim pos As New Point(10, 10)
        ' get all tables in the dataset
        For Each dt As DataTable In dataSet.Tables
            ' but we're only interested in the toplevel tables
            If dt.ParentRelations.Count = 0 Then
                '
                '						* Rule 1:
                '						* A top level table will be a top level element in the mSchema that
                '						* is of a complex type.  The element name will be the table name.
                '						* What we want to identify is the complex type that the table references,
                '						* so that we can determine the data types of the columns.
                '						* 
                '						* Any other rules???
                '						

                Dim el As XmlSchemaElement = GetGlobalElement(dt.TableName)
                If Not el Is Nothing Then
                    Dim ct As XmlSchemaComplexType
                    ' references a global complex type?
                    'todo what is Schema Globle type

                    If el.SchemaTypeName.Name <> "" Then
                        Dim name As String = If(el.RefName.Name <> "", el.RefName.Name, el.SchemaTypeName.Name)
                        ct = GetGlobalComplexType(name)
                    Else
                        ' contains a complex type?
                        ct = TryCast(el.SchemaType, XmlSchemaComplexType)
                    End If
                    If Not ct Is Nothing Then
                        'todo add treenode to the treeview
                        TreeView.Nodes.Add(ct.Name)
                        Dim p2 As Point = ConstructGUI(pos.X, pos.Y, dt, pnlDynForm, ct)
                        pos.Y += p2.Y
                    End If
                End If
            End If
        Next
    End Sub
#End Region
#Region "Functions That Inspect The Schema"

    Private Function GetLocalAttribute(ByVal ct As XmlSchemaComplexType, ByVal name As String) As XmlSchemaAttribute
        For i As Integer = 0 To ct.Attributes.Count - 1
            Dim attr As XmlSchemaAttribute = TryCast(ct.Attributes(i), XmlSchemaAttribute)
            If attr IsNot Nothing Then
                If attr.QualifiedName.Name = name Then
                    Return attr
                End If
            End If
        Next
        Return Nothing
    End Function

    Private Function GetLocalElement(ByVal ct As XmlSchemaComplexType, ByVal name As String) As XmlSchemaElement
        Dim seq As XmlSchemaSequence = TryCast(ct.Particle, XmlSchemaSequence)
        If seq IsNot Nothing Then
            For i As Integer = 0 To seq.Items.Count - 1
                Dim el As XmlSchemaElement = TryCast(seq.Items(i), XmlSchemaElement)
                If el IsNot Nothing Then
                    If el.QualifiedName.Name = name Then
                        Return el
                    End If
                End If
            Next
        End If
        Return Nothing
    End Function

    Private Function GetLocalComplexType(ByVal el As XmlSchemaElement) As XmlSchemaComplexType
        Dim obj As XmlSchemaComplexType = TryCast(el.SchemaType, XmlSchemaComplexType)
        Return obj
    End Function

    Private Function GetGlobalElement(ByVal name As String) As XmlSchemaElement
        Dim qname As New XmlQualifiedName(name, mSchema.TargetNamespace)
        Dim obj As XmlSchemaObject = mSchema.Elements(qname)
        Return TryCast(obj, XmlSchemaElement)
    End Function

    Private Function GetGlobalSimpleType(ByVal name As String) As XmlSchemaSimpleType
        For i As Integer = 0 To mSchema.Items.Count - 1
            Dim obj As XmlSchemaSimpleType = TryCast(mSchema.Items(i), XmlSchemaSimpleType)
            If obj IsNot Nothing Then
                If obj.Name = name Then
                    Return obj
                End If
            End If
        Next
        Return Nothing
    End Function

    Private Function GetGlobalAttribute(ByVal name As String) As XmlSchemaAttribute
        Dim obj As XmlSchemaAttribute = TryCast(mSchema.Attributes(New XmlQualifiedName(name, mSchema.TargetNamespace)), XmlSchemaAttribute)
        Return obj
    End Function

    Private Function GetGlobalComplexType(ByVal name As String) As XmlSchemaComplexType
        For i As Integer = 0 To mSchema.Items.Count - 1
            Dim obj As XmlSchemaComplexType = TryCast(mSchema.Items(i), XmlSchemaComplexType)
            If obj IsNot Nothing Then
                If obj.Name = name Then
                    Return obj
                End If
            Else
                Dim el2 As XmlSchemaElement = TryCast(mSchema.Items(i), XmlSchemaElement)
                If el2 IsNot Nothing Then
                    If TypeOf el2.SchemaType Is XmlSchemaComplexType Then
                        obj = TryCast(el2.SchemaType, XmlSchemaComplexType)
                        If DirectCast(mSchema.Items(i), XmlSchemaElement).Name = name Then
                            ' *** The returning complex type does not have any associated qualified name!!! ****
                            Return obj
                        End If
                    End If
                End If
            End If
        Next
        Return Nothing
    End Function

    Private Sub GetFacetInfo(ByVal ti As TypeInfo, ByVal rs As XmlSchemaSimpleTypeRestriction)
        For Each facet As XmlSchemaFacet In rs.Facets
            ' There's probably a better way to do this with reflection or some such
            ' process, but this old C++ programmers don't learn new tricks easily.
            Select Case facet.[GetType]().ToString()
                Case "System.Xml.Schema.XmlSchemaLengthFacet"
                    If True Then
                        ti.length = facet.Value
                        Exit Select
                    End If

                Case "System.Xml.Schema.XmlSchemaMinLengthFacet"
                    If True Then
                        ti.minLength = facet.Value
                        Exit Select
                    End If

                Case "System.Xml.Schema.XmlSchemaMaxLengthFacet"
                    If True Then
                        ti.maxLength = facet.Value
                        Exit Select
                    End If

                Case "System.Xml.Schema.XmlSchemaPatternFacet"
                    If True Then
                        ti.pattern = facet.Value
                        Exit Select
                    End If

                Case "System.Xml.Schema.XmlSchemaEnumerationFacet"
                    If True Then
                        ti.enumeration.Add(facet.Value)
                        Exit Select
                    End If

                Case "System.Xml.Schema.XmlSchemaMaxInclusiveFacet"
                    If True Then
                        ti.maxInclusive = facet.Value
                        Exit Select
                    End If

                Case "System.Xml.Schema.XmlSchemaMaxExclusiveFacet"
                    If True Then
                        ti.maxExclusive = facet.Value
                        Exit Select
                    End If

                Case "System.Xml.Schema.XmlSchemaMinInclusiveFacet"
                    If True Then
                        ti.minInclusive = facet.Value
                        Exit Select
                    End If

                Case "System.Xml.Schema.XmlSchemaMinExclusiveFacet"
                    If True Then
                        ti.minExclusive = facet.Value
                        Exit Select
                    End If

                Case "System.Xml.Schema.XmlSchemaFractionDigitsFacet"
                    If True Then
                        ti.fractionDigits = facet.Value
                        Exit Select
                    End If

                Case "System.Xml.Schema.XmlSchemaTotalDigitsFacet"
                    If True Then
                        ti.totalDigits = facet.Value
                        Exit Select
                    End If

                Case "System.Xml.Schema.XmlSchemaWhiteSpaceFacet"
                    If True Then
                        ti.whiteSpace = facet.Value
                        Exit Select
                    End If
            End Select
        Next
    End Sub

    Private Function GetTypeInfo(ByVal ct As XmlSchemaComplexType, ByVal name As String) As TypeInfo
        Dim ti As TypeInfo = Nothing

        ' is it an element?
        Dim el As XmlSchemaElement = Nothing
        el = GetLocalElement(ct, name)

        ' *** 5/10/2003 *** Search global element list also
        If el Is Nothing Then
            el = GetGlobalElement(name)
        End If

        ' or is it an attribute?
        Dim attr As XmlSchemaAttribute = Nothing
        If ct IsNot Nothing Then
            attr = GetLocalAttribute(ct, name)
        End If

        If el IsNot Nothing Then
            ' is it an element of simple type?
            If TypeOf el.SchemaType Is XmlSchemaSimpleType Then
                ' (paths have been tested)
                ' yes...get the restriction base to find the type
                Dim st As XmlSchemaSimpleType = TryCast(el.SchemaType, XmlSchemaSimpleType)
                Dim rest As XmlSchemaSimpleTypeRestriction = TryCast(st.Content, XmlSchemaSimpleTypeRestriction)
                If rest IsNot Nothing Then
                    If rest.BaseTypeName.[Namespace] = "" Then
                        st = GetGlobalSimpleType(rest.BaseTypeName.Name)
                        rest = TryCast(st.Content, XmlSchemaSimpleTypeRestriction)
                        Dim typename As String = rest.BaseTypeName.Name
                        ti = New TypeInfo(typename)
                        GetFacetInfo(ti, rest)
                    Else
                        Dim typename As String = rest.BaseTypeName.Name
                        ti = New TypeInfo(typename)
                        GetFacetInfo(ti, rest)
                    End If
                End If
            Else
                ' no...get the attribute type
                ' does it reference a global element?
                If el.RefName.Name <> "" Then
                    ' (path has been tested)
                    el = GetGlobalElement(el.RefName.Name)
                    If el IsNot Nothing Then
                        Dim typename As String = el.SchemaTypeName.Name
                        ti = New TypeInfo(typename)
                    End If
                Else
                    ' (path has been tested)
                    ' no...the type is specified in the element

                    ' Does this reference a global simple type?
                    Dim typename As String = el.SchemaTypeName.Name
                    If el.SchemaTypeName.[Namespace] = "" Then
                        Dim st As XmlSchemaSimpleType = GetGlobalSimpleType(typename)
                        Dim rest As XmlSchemaSimpleTypeRestriction = TryCast(st.Content, XmlSchemaSimpleTypeRestriction)
                        If rest IsNot Nothing Then
                            typename = rest.BaseTypeName.Name
                            ti = New TypeInfo(typename)
                            GetFacetInfo(ti, rest)
                        End If
                    Else
                        ti = New TypeInfo(typename)
                    End If
                End If
            End If
        ElseIf attr IsNot Nothing Then
            ' does it reference a global attribute?
            If attr.RefName.Name <> "" Then
                ' yes...get the type of the reference
                ' !!! PATH HAS NOT BEEN TESTED !!!
                attr = GetGlobalAttribute(attr.RefName.Name)
                If attr IsNot Nothing Then
                    Dim typename As String = attr.SchemaTypeName.Name
                    ti = New TypeInfo(typename)
                End If
            Else
                ' no...get the type of the attribute
                ' is it of simple type defined globally?
                If TypeOf attr.AttributeSchemaType Is XmlSchemaSimpleType Then
                    ' (path has been tested)
                    Dim st As XmlSchemaSimpleType = GetGlobalSimpleType(attr.SchemaTypeName.Name)
                    If st IsNot Nothing Then
                        Dim rest As XmlSchemaSimpleTypeRestriction = TryCast(st.Content, XmlSchemaSimpleTypeRestriction)
                        If rest IsNot Nothing Then
                            Dim typename As String = rest.BaseTypeName.Name
                            ti = New TypeInfo(typename)
                            GetFacetInfo(ti, rest)
                        End If
                    End If
                Else
                    ' (path has been tested)
                    Dim typename As String = attr.SchemaTypeName.Name
                    ti = New TypeInfo(typename)
                End If
            End If
        End If
        Return ti
    End Function

#End Region
    Public Class TypeInfo
        Public Sub New()
            typeName = ""
        End Sub
        Public Sub New(ByVal typeName As String)
            Me.typeName = typeName
            length = "-1"
            minLength = "-1"
            maxLength = "-1"
            pattern = ""
            maxInclusive = Nothing
            maxExclusive = Nothing
            minInclusive = Nothing
            minExclusive = Nothing
            fractionDigits = "-1"
            totalDigits = "-1"
            whiteSpace = ""
            enumeration = New ArrayList()
        End Sub

        Public typeName As String

        ' facet information
        Public length As String
        Public minLength As String
        Public maxLength As String
        Public pattern As String
        Public maxInclusive As String
        Public maxExclusive As String
        Public minInclusive As String
        Public minExclusive As String
        Public fractionDigits As String
        Public totalDigits As String
        Public whiteSpace As String
        ' "preserve", "replace", or "collapse"
        Public enumeration As ArrayList
    End Class

    Public Class TableInfo
        Public Sub New()
            tb = Nothing
            rows = 0
            pos = 0
        End Sub

        Public tb As TextBox
        Public rows As Integer
        Public pos As Integer
        Public dataRows As DataRow()
    End Class

End Class
